package com.suning.sawp.service.impl.promotion;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.stereotype.Service;

import com.suning.sawp.constants.ErrorCodeConstants;
import com.suning.sawp.constants.LoggerConstants;
import com.suning.sawp.dto.common.ReturnMsg;
import com.suning.sawp.exception.MobileException;
import com.suning.sawp.intf.dao.HorizPromotionDaoService;
import com.suning.sawp.intf.promotion.ImportPromotionService;
import com.suning.sawp.po.promotion.HorizProActivity;
import com.suning.sawp.po.promotion.HorizProCoupon;
import com.suning.sawp.po.promotion.HorizProRecord;
import com.suning.sawp.service.util.ExcelUtils;

/**
 * 
 * 导入异页券接口<br> 
 * 〈功能详细描述〉
 *
 * @author 14062606
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Service
public class ImportPromotionServiceImpl implements ImportPromotionService{

	private static final Logger LOGGER = LoggerFactory.getLogger(LoggerConstants.SAWP_INTEGRATION);
	
	@Resource
	MongoOperations mongoTemplate;
	
	@Resource
	MongoOperations safeMongoTemplate;
	
	@Resource
	HorizPromotionDaoService horizPromotionDaoService;
	
	private static long tmpID = 0;
	 
	private static boolean tmpIDlocked = false;
	
	private static Pattern HORIZ_ID_PATTERN = Pattern.compile("^\\d{12}$");
	
	public static void main(String[] args) {
	    Matcher matcher = HORIZ_ID_PATTERN.matcher("123456789011");
        System.out.println(matcher.matches());
    }
	
	public ReturnMsg<Integer> importPromotion(String activityName, String proActivityId, 
			String activitySecretKey, String proActivityName, String actRemainCount,
			String startTime, String endTime, String staffId, String fileName, InputStream inputStream) {
		ReturnMsg<Integer> rsg = new ReturnMsg<Integer>();
		if (!fileName.endsWith(".xlsx")) {
		    rsg.setError(ErrorCodeConstants.ERR_0008);
		    return rsg;
		}
		String importBatch = String.valueOf(getUniqueId());
		int importNum = 0;
		try {
		    // 与产品确认新增活动逻辑调整为，在后台刷新第一页活动列表时与促销中心做同步，导入无需再考虑新增活动情况
			// 查询促销活动ID对应活动信息，计算活动所属剩余可导入券数量（促销中心券总量-实际已导入券数量）
			HorizProActivity horizProActivity = horizPromotionDaoService
			        .findHorizProActivityByActivityId(proActivityId);
			if (null != horizProActivity) {
			    int remainImportCount = horizProActivity.getActCount() 
			            - horizProActivity.getActualActCount();
			    List<Object []> promotionList = ExcelUtils.getListFromExcel(inputStream);
			    // excel表里的数据小于剩余券数量，可以导入，否则，提示错误信息
			    if (CollectionUtils.isNotEmpty(promotionList)) {
			        importNum = promotionList.size();
			        if (promotionList.size() <= remainImportCount) {
			            try {
		                    // 将异业优惠券记录导入数据库
		                    importHorizCoupon(promotionList, proActivityId, proActivityName, activitySecretKey, importBatch);
		                    // 导入成功更新，实际导入券数量
		                    horizPromotionDaoService.updateActivityActualActCount(staffId, proActivityId, promotionList.size());
		                } catch (DuplicateKeyException e) {
		                    // 违反唯一主键冲突异常，有相同异业券号,先删除已导入的数据
		                    deleteNoUseHorizCoupon(importBatch, staffId, proActivityId);
		                    rsg.setError(ErrorCodeConstants.ERR_1011);
		                    LOGGER.error("导入失败，有相同异业券号,error=",e);
		                } catch (MobileException e) {
		                    // 导入的异业券号存在不合法的情况, 先删除已导入的数据
		                    deleteNoUseHorizCoupon(importBatch, staffId, proActivityId);
		                    rsg.setError(e.getErrorCode());
                            LOGGER.error("导入失败，导入的异业券号存在不合法的情况,error=",e);
                        }
			        } else {
                        rsg.setError(ErrorCodeConstants.ERR_1012, remainImportCount);
			        }
			    }
			} else {
			    // 促销活动在库里不存在，提示促销活动不存在
			    rsg.setError(ErrorCodeConstants.ERR_1010);
			}
			
		} catch (Exception e) {
			rsg.setError(ErrorCodeConstants.ERR_0002);
			LOGGER.error("导入异业券失败,staffId="+staffId+",activityName="+activityName+
					",proActivityId="+proActivityId+",proActivityName="+proActivityName+",error=", e);
		}
		
		// 导入成功记录导入记录
		if (ReturnMsg.SUCCESS.equals(rsg.getRetFlag())) {
		    HorizProRecord record = new HorizProRecord();
	        record.setOperator(staffId);
	        record.setOperateTime(new Date());
	        record.setActivityId(proActivityId);
	        record.setFileName(fileName);
	        record.setImportBatch(importBatch);
	        record.setImportNum(importNum);
	        mongoTemplate.save(record);
	        rsg.setData(importNum);
		}
		return rsg;
	}

	/**
	 * 
	 * 功能描述: 根据批次号删除已导入的优惠券<br>
	 * 〈功能详细描述〉
	 *
	 * @param importBatch
	 * @see [相关类/方法](可选)
	 * @since [产品/模块版本](可选)
	 */
	private void deleteNoUseHorizCoupon(String importBatch, String staffId, String proActivityId){
	    // 删除已导入的优惠券
		int size = horizPromotionDaoService.deleteHorizCouponByimpBatchCd(importBatch);
		// 更新次促销活动对应实际券导入量
		horizPromotionDaoService.updateActivityActualActCount(staffId, proActivityId, -size);
	}
	
	/**
	 * 生成唯一序列号
	 * @return
	 */
	private static long getUniqueId() {
		long ltime = 0;
		while (true) {
			if (tmpIDlocked == false) {
				tmpIDlocked = true;
				ltime = Long.valueOf(new SimpleDateFormat("yyMMddhhmmssSSS")
						.format(new Date()).toString()) * 10000;
				if (tmpID < ltime) {
					tmpID = ltime;
				} else {
					tmpID = tmpID + 1;
					ltime = tmpID;
				}
				tmpIDlocked = false;
				return ltime;
			}
		}
	}
	
	/**
	 * 将异业优惠券记录导入数据库
	 * @param promotionList
	 * @param proActivityId
	 * @param proActivityName
	 * @param activitySecretKey
	 */
	private void importHorizCoupon(List<Object []> promotionList, String proActivityId, 
			String proActivityName, String activitySecretKey, String importBatch) throws MobileException {
		List<Object []> tempList = new ArrayList<Object []>();
		for (int i = 0; i < promotionList.size(); i++) {  
			tempList.add(promotionList.get(i));
			//每1000条数据执行一次添加
        	if ((i+1)%1000==0 || (i+1)==promotionList.size()){
        		List<HorizProCoupon> proCouponList = new ArrayList<HorizProCoupon>();
        		for (Object[] p : tempList){
        			HorizProCoupon proCoupon = new HorizProCoupon();
        			//导入优惠券记录时，只需增加 异业券号，促销中心活动编码，促销中心活动名称，活动秘钥字段
        			// 判断异业券号是否符合12位数字
        			Matcher matcher = HORIZ_ID_PATTERN.matcher(p[1].toString());
        			if (matcher.matches()) {
        			    proCoupon.setHorizId(p[1].toString());
                        proCoupon.setProActivityId(proActivityId);
                        proCoupon.setProActivityName(proActivityName);
                        proCoupon.setActivitySecretKey(activitySecretKey);
                        proCoupon.setImportBatch(importBatch);
                        proCouponList.add(proCoupon);
        			} else {
        			    throw new MobileException(ErrorCodeConstants.ERR_1014);
        			}
        		}
        		safeMongoTemplate.insertAll(proCouponList);
        		tempList.clear();
        	}
        }
	}
	
}
